<?php

namespace Modules\Custessa\Services;

use Exception;
use Modules\Custessa\Entity\Widget;

class WidgetRegistry {

    const CONTEXT_DASHBOARD = 'dashboard';
    const CONTEXT_TEMPLATE_DASHBOARD = 'template_dashboard';

    /**
     * Associative array of registered widgets. Key is widget unique identifier.
     */
    protected $registered = [];

    /**
     * Register widget
     *
     * @param string $widgetid  Unique id used to access widget from application.
     * @param string $widget    FQCN of registered widget, example: Modules\Example\Widgets\ExampleWidget
     */
    public function register(string $widgetid, Widget $widget): WidgetRegistry {
        if ($this->has($widgetid)) {
            throw new Exception("Widget with id {$widgetid} already registered.");
        }

        $this->registered[$widgetid] = $widget;

        return $this;
    }

    /**
     * Allows to access regitered widget as WidgetManager property. Widget class will be created only once
     * on first access. Return null if widget does not exists.
     */
    public function get(string $widgetid) {
        if (!$this->has($widgetid)) {
            throw new Exception("Widget with id {$widgetid} not found.");
        }

        return $this->registered[$widgetid];
    }

    /**
     * Check is widget registered.
     *
     * @param string $widgetid  Widget unique id to check.
     */
    public function has(string $widgetid): bool {
        return isset($this->registered[$widgetid]);
    }

    /**
     * Get registered widgets list as associative array with widget id as key and widget translated label as value.
     *
     * @param callable $filter  Function to filter out list entries. If defined should return true to keep widget
     *                          in list, false otherwise. Will recieve $widget instance as argument.
     */
    public function list(?callable $filter = null): array {
        $widgets = [];

        foreach ($this->registered as $widgetid => $widget) {
            if ($filter === null || $filter($widget)) {
                $widgets[$widgetid] = $widget->getLabel();
            }
        }

        return $widgets;
    }

    public function __get($widgetid) {
        return $this->get($widgetid);
    }

    public function __set($widgetid, $widget) {
        return $this->register($widgetid, $widget);
    }
}